package com.see.front.data;

import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Logger;

import com.see.services.GoogleInitializer;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.ProgressIndicator;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.FailedEvent;
import com.vaadin.ui.Upload.FinishedEvent;
import com.vaadin.ui.Upload.Receiver;
import com.vaadin.ui.Upload.StartedEvent;
import com.vaadin.ui.Upload.SucceededEvent;
import com.vaadin.ui.VerticalLayout;

@SuppressWarnings("serial")
public class StaticDataUploader extends VerticalLayout {

	private Label state = new Label();
	private Label result = new Label();
	private Label fileName = new Label();
	private Label fileType = new Label();
	private Label textualProgress = new Label();

	private ProgressIndicator pi = new ProgressIndicator();

	private LineBreakCounter counter = new LineBreakCounter();

	private Upload upload = new Upload("Upload file", counter);
	
	private static final Logger logger = Logger.getLogger(StaticDataUploader.class.getName());


	public StaticDataUploader() {
		setSpacing(true);

		// make analyzing start immediatedly when file is selected
		upload.setImmediate(true);
		upload.setButtonCaption("Click here to select a file");
		addComponent(upload);

		final Button cancelProcessing = new Button("Cancel");
		cancelProcessing.addListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				upload.interruptUpload();
			}
		});
		cancelProcessing.setVisible(false);
		cancelProcessing.setStyleName("small");

		Panel p = new Panel("Status");
		p.setSizeUndefined();
		FormLayout l = new FormLayout();
		l.setMargin(true);
		p.setContent(l);
		HorizontalLayout stateLayout = new HorizontalLayout();
		stateLayout.setSpacing(true);
		stateLayout.addComponent(state);
		stateLayout.addComponent(cancelProcessing);
		stateLayout.setCaption("Current state");
		state.setValue("Idle");
		l.addComponent(stateLayout);
		fileName.setCaption("File name");
		l.addComponent(fileName);
		fileType.setCaption("File type");
		l.addComponent(fileType);
		result.setCaption("Line breaks counted");
		l.addComponent(result);
		pi.setCaption("Progress");
		pi.setVisible(false);
		l.addComponent(pi);
		textualProgress.setVisible(false);
		l.addComponent(textualProgress);

		addComponent(p);

		upload.addListener(new Upload.StartedListener() {
			public void uploadStarted(StartedEvent event) {
				// this method gets called immediatedly after upload is
				// started
				pi.setValue(0f);
				pi.setVisible(true);
				pi.setPollingInterval(500); // hit server frequantly to get
				textualProgress.setVisible(true);
				// updates to client
				state.setValue("Uploading");
				fileName.setValue(event.getFilename());
				fileType.setValue(event.getMIMEType());

				cancelProcessing.setVisible(true);
			}
		});

		upload.addListener(new Upload.ProgressListener() {
			public void updateProgress(long readBytes, long contentLength) {
				// this method gets called several times during the update
				pi.setValue(new Float(readBytes / (float) contentLength));
				textualProgress.setValue("Processed " + readBytes
						+ " bytes of " + contentLength);
				result.setValue(counter.getLineBreakCount() + " (counting...)");
			}

		});

		upload.addListener(new Upload.SucceededListener() {
			public void uploadSucceeded(SucceededEvent event) {
				result.setValue(counter.getLineBreakCount() + " (total)");
			}
		});

		upload.addListener(new Upload.FailedListener() {
			public void uploadFailed(FailedEvent event) {
				result.setValue(counter.getLineBreakCount()
						+ " (counting interrupted at "
						+ Math.round(100 * (Float) pi.getValue()) + "%)");
				upload = new Upload("Upload file", counter);
			}
		});

		upload.addListener(new Upload.FinishedListener() {
			public void uploadFinished(FinishedEvent event) {
				state.setValue("File uploaded Completed!!!");
				pi.setVisible(false);
				textualProgress.setVisible(false);
				cancelProcessing.setVisible(false);

				String fileContent = counter.getFileContent().trim();
				String symbols[] = fileContent.split("\\n");
				GoogleInitializer initilizer = new GoogleInitializer();
				initilizer.initSymbolData(symbols);
				logger.info("Symbols inserted completed!!");

			}
		});

	}

	public static class LineBreakCounter implements Receiver {

		private String fileName;
		private String mtype;

		private int counter;
		private int total;
		private boolean sleep;

		private StringBuilder content = new StringBuilder();

		/**
		 * return an OutputStream that simply counts lineends
		 */
		public OutputStream receiveUpload(String filename, String MIMEType) {
			counter = 0;
			total = 0;
			fileName = filename;
			mtype = MIMEType;
			return new OutputStream() {
				private static final int searchedByte = '\n';

				@Override
				public void write(int b) throws IOException {
					content.append((char) b);
					total++;
					if (b == searchedByte) {
						counter++;
					}

				}
			};
		}

		public String getFileName() {
			return fileName;
		}

		public String getMimeType() {
			return mtype;
		}

		public int getLineBreakCount() {
			return counter;
		}

		public void setSlow(boolean value) {
			sleep = value;
		}

		public String getFileContent() {
			return content.toString();
		}

	}

}
